#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <mach/platform.h>

#define LED_ON  0x100001
#define LED_OFF 0x100002

struct leds_desc{
    char *name;
    int gpio;
};
struct leds_desc leds[]={
    {"led_bedroom", PAD_GPIO_C+12},
    {"led_saloon",  PAD_GPIO_C+7 },
    {"led_kitchen",  PAD_GPIO_C+11},
    {"led_restroom",PAD_GPIO_B+26},
};
struct miscdevice leds_misc;

long leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    int kindex;
    int status;
    int ret;
    ret=copy_from_user(&kindex,(int *)arg,4);
    switch(cmd){
        case LED_ON:
            status=0;
            break;
        case LED_OFF:
            status=1;
            break;
        default:
            return -EINVAL;
    }
    if(kindex<4&&kindex>=0){
    gpio_set_value(leds[kindex].gpio, status);
    }
    return 0;
}
struct file_operations leds_fops={
    .owner          = THIS_MODULE,
    .unlocked_ioctl = leds_ioctl,
};
struct miscdevice leds_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = "leds",
    .fops  = &leds_fops,
};

static int __init leds_init(void){
  int i=0;
  for(;i<ARRAY_SIZE(leds);i++){
    gpio_request(leds[i].gpio,leds[i].name);
    gpio_direction_output(leds[i].gpio,1);
  }
  misc_register(&leds_misc);
  return 0;
}

static void __exit leds_exit(void){
    int i=0;

    misc_deregister(&leds_misc);
    for(;i<ARRAY_SIZE(leds);i++){
        gpio_free(leds[i].gpio);
    }
}
module_init(leds_init);
module_exit(leds_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGY");
